/**
 * Copyright (c) 2010 BullionXpress.com,
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @author BullionXpress.com
 */
package com.bullionxpress.client.view;

import com.bullionxpress.shared.model.Command;
import com.bullionxpress.client.controller.CommandController;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import com.javadocking.DockingManager;
import com.javadocking.dock.BorderDock;
import com.javadocking.dock.CompositeLineDock;
import com.javadocking.dock.FloatDock;
import com.javadocking.dock.GridDock;
import com.javadocking.dock.LineDock;
import com.javadocking.dock.Position;
import com.javadocking.dock.SplitDock;
import com.javadocking.dock.TabDock;
import com.javadocking.dock.docker.BorderDocker;
import com.javadocking.dock.factory.CompositeToolBarDockFactory;
import com.javadocking.dock.factory.ToolBarDockFactory;
import com.javadocking.dockable.ButtonDockable;
import com.javadocking.dockable.DefaultDockable;
import com.javadocking.dockable.Dockable;
import com.javadocking.dockable.DockableState;
import com.javadocking.dockable.DockingMode;
import com.javadocking.dockable.StateActionDockable;
import com.javadocking.dockable.action.DefaultDockableStateActionFactory;
import com.javadocking.drag.DragListener;
import com.javadocking.model.DefaultDockingPath;
import com.javadocking.model.DockModel;
import com.javadocking.model.DockingPath;
import com.javadocking.model.FloatDockModel;

import com.javadocking.util.LAF;
import com.javadocking.util.LookAndFeelUtil;
import com.javadocking.util.SampleComponentFactory;
import com.javadocking.util.ToolBarButton;
import com.javadocking.visualizer.DockingMinimizer;
import com.javadocking.visualizer.FloatExternalizer;
import com.javadocking.visualizer.SingleMaximizer;
import java.awt.Color;
import java.awt.event.ComponentListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JDialog;
import javax.swing.JSeparator;
import com.bullionxpress.client.application.ClientGlobals;
import com.bullionxpress.shared.application.Application;
import com.bullionxpress.shared.application.SharedGlobals;
import com.bullionxpress.shared.service.ChartService;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;



public class DockingFrame extends JPanel {

    // Static fields.
    public static final int FRAME_WIDTH = 900;
    public static final int FRAME_HEIGHT = 650;
    // Fields.
    /** All the dockables of the application. */
    private Dockable[] dockables;

    /** All the dockables for buttons of the application. */
    //private Dockable[] buttonDockables;
    public DockingFrame() {
    }

    // Constructors.
    public DockingFrame(final JFrame frame) {

        super(new BorderLayout());
        // Create the dock model for the docks, minimizer and maximizer.
        FloatDockModel dockModel = new FloatDockModel("workspace.dck");
        String frameId = "frame";
        dockModel.addOwner(frameId, frame);

        // Give the dock model to the docking manager.
        DockingManager.setDockModel(dockModel);

        // Set our custom component factory.
        DockingManager.setComponentFactory(new SampleComponentFactory());

        // Create the content components.
        JPanel book = new JPanel();
        book.setBackground(Color.pink);

        AccountView details = new AccountView();
        Console console = new Console();
        OrderListView orders = new OrderListView();
        PositionListView positions = new PositionListView();
        InstrumentInspectorView inspector = new InstrumentInspectorView();

        TransactionListView transactions = new TransactionListView();

        com.bullionxpress.client.view.ChartView chart = new com.bullionxpress.client.view.ChartView();
        ClientGlobals.chartView = chart;
        ScrollBarPanel scrollBarPanel = new ScrollBarPanel(chart);
        ClientGlobals.scrollBarPanel = scrollBarPanel;
        ChartService producer = null;
        producer = ClientGlobals.chartService;



        // The arrays for the dockables and button dockables.
        dockables = new Dockable[6];
        //buttonDockables = new Dockable[42];


        // Create the dockables around the content components.
        //new ImageIcon(getClass().getResource("/com/javadocking/resources/images/binocular12.gif"))
        dockables[DockingTabList.DETAILS] = createDockable("Account Details", details, "Account Details", null, "");
        dockables[DockingTabList.CHART] = createDockable("Chart", scrollBarPanel, "Chart", null, "");
        dockables[DockingTabList.CONSOLE] = createDockable("Console", console, "Console", null, "");
        dockables[DockingTabList.ORDERS] = createDockable("Orders", orders, "Orders", null, "");
        dockables[DockingTabList.TRANSACTIONS] = createDockable("Transactions", transactions, "Transactions", null, "");
        dockables[DockingTabList.POSITIONS] = createDockable("Positions", positions, "Positions", null, "");
        //dockables[INSPECTOR] = createDockable("Inspector", inspector, "Inspector", new ImageIcon(getClass().getResource("/com/javadocking/resources/images/binocular12.gif")), "Find a text");

        ClientGlobals.registry.put("Console", console);

        // The dockable with the find panel may not be maximized.
        ((DefaultDockable) dockables[DockingTabList.DETAILS]).setPossibleStates(DockableState.CLOSED | DockableState.NORMAL | DockableState.MINIMIZED | DockableState.EXTERNALIZED);

        // Add actions to the dockables.
        for (int index = 0; index < dockables.length; index++) {
            if (index == DockingTabList.DETAILS) {
                // All actions, except the maximize.
                dockables[index] = addLimitActions(dockables[index]);
            } else {
                // All actions.
                dockables[index] = addAllActions(dockables[index]);
            }
        }


        // Give the float dock a different child dock factory.
        // We don't want the floating docks to be splittable.
        //FloatDock floatDock = dockModel.getFloatDock(frame);
        //floatDock.setChildDockFactory(new LeafDockFactory(false));

        // Create the tab docks.
        TabDock centerTabbedDock = new TabDock();
        TabDock bottomTabbedDock = new TabDock();
        //TabDock leftTabbedDock = new TabDock();

        // Add the dockables to these tab docks.
        centerTabbedDock.addDockable(dockables[DockingTabList.CHART], new Position(0));
        centerTabbedDock.setSelectedDockable(dockables[DockingTabList.CHART]);
        bottomTabbedDock.addDockable(dockables[DockingTabList.CONSOLE], new Position(0));
        bottomTabbedDock.addDockable(dockables[DockingTabList.ORDERS], new Position(0));
        bottomTabbedDock.addDockable(dockables[DockingTabList.TRANSACTIONS], new Position(0));
        bottomTabbedDock.addDockable(dockables[DockingTabList.POSITIONS], new Position(0));
        bottomTabbedDock.setSelectedDockable(dockables[DockingTabList.POSITIONS]);
        TabDock td1 = new TabDock();
        td1.addDockable(dockables[DockingTabList.DETAILS], new Position(0));

        // The 4 windows have to be splittable.
        final SplitDock centerSplitDock = new SplitDock();
        centerSplitDock.addChildDock(centerTabbedDock, new Position(Position.CENTER));
        centerSplitDock.addChildDock(td1, new Position(Position.RIGHT));
        centerSplitDock.setDividerLocation(680);
        SplitDock bottomSplitDock = new SplitDock();
        bottomSplitDock.addChildDock(bottomTabbedDock, new Position(Position.CENTER));
        final SplitDock rightSplitDock = new SplitDock();
        rightSplitDock.addChildDock(centerSplitDock, new Position(Position.CENTER));
        rightSplitDock.addChildDock(bottomSplitDock, new Position(Position.BOTTOM));
        rightSplitDock.setDividerLocation(480);

        frame.addComponentListener(new ComponentListener() {

            public void componentResized(ComponentEvent e) {
                int locRight = frame.getSize().width - 280;
                int locBottom = frame.getSize().height - 240;
                centerSplitDock.setDividerLocation(locRight);
                rightSplitDock.setDividerLocation(locBottom);
            }

            public void componentMoved(ComponentEvent e) {
            }

            public void componentShown(ComponentEvent e) {
            }

            public void componentHidden(ComponentEvent e) {
            }
        });

        // Add the root dock to the dock model.
        dockModel.addRootDock("totalDock", rightSplitDock, frame);

        // Dockable 10 should float. Add dockable 10 to the float dock of the dock model (this is a default root dock).
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

        // Create a maximizer and add it to the dock model.
        SingleMaximizer maximizePanel = new SingleMaximizer(rightSplitDock);
        dockModel.addVisualizer("maximizer", maximizePanel, frame);

        // Create a docking minimizer and add it to the dock model.
        BorderDock minimizerBorderDock = new BorderDock(new ToolBarDockFactory());
        minimizerBorderDock.setMode(BorderDock.MODE_MINIMIZE_BAR);
        minimizerBorderDock.setCenterComponent(maximizePanel);

        BorderDocker borderDocker = new BorderDocker();
        borderDocker.setBorderDock(minimizerBorderDock);
        DockingMinimizer minimizer = new DockingMinimizer(borderDocker);
        dockModel.addVisualizer("minimizer", minimizer, frame);

        // Add an externalizer to the dock model.
        dockModel.addVisualizer("externalizer", new FloatExternalizer(frame), frame);

        // Create the tool bar border dock for the buttons.
        BorderDock toolBarBorderDock = new BorderDock(new CompositeToolBarDockFactory(), minimizerBorderDock);
        toolBarBorderDock.setMode(BorderDock.MODE_TOOL_BAR);
        CompositeLineDock compositeToolBarDock1 = new CompositeLineDock(CompositeLineDock.ORIENTATION_HORIZONTAL, false,
                new ToolBarDockFactory(), DockingMode.HORIZONTAL_TOOLBAR, DockingMode.VERTICAL_TOOLBAR);
        CompositeLineDock compositeToolBarDock2 = new CompositeLineDock(CompositeLineDock.ORIENTATION_VERTICAL, false,
                new ToolBarDockFactory(), DockingMode.HORIZONTAL_TOOLBAR, DockingMode.VERTICAL_TOOLBAR);
        toolBarBorderDock.setDock(compositeToolBarDock1, Position.TOP);
        toolBarBorderDock.setDock(compositeToolBarDock2, Position.LEFT);

        // Add this dock also as root dock to the dock model.
        dockModel.addRootDock("toolBarBorderDock", toolBarBorderDock, frame);

        // Add the tool bar border dock to this panel.
        this.add(toolBarBorderDock, BorderLayout.CENTER);

        // The line docks and one grid dock for the buttons.
        LineDock toolBarDock1 = new LineDock(LineDock.ORIENTATION_HORIZONTAL, false, DockingMode.HORIZONTAL_TOOLBAR, DockingMode.VERTICAL_TOOLBAR);
        LineDock toolBarDock2 = new LineDock(LineDock.ORIENTATION_HORIZONTAL, false, DockingMode.HORIZONTAL_TOOLBAR, DockingMode.VERTICAL_TOOLBAR);
        LineDock toolBarDock3 = new LineDock(LineDock.ORIENTATION_HORIZONTAL, false, DockingMode.HORIZONTAL_TOOLBAR, DockingMode.VERTICAL_TOOLBAR);
        LineDock toolBarDock4 = new LineDock(LineDock.ORIENTATION_HORIZONTAL, false, DockingMode.HORIZONTAL_TOOLBAR, DockingMode.VERTICAL_TOOLBAR);
        LineDock toolBarDock5 = new LineDock(LineDock.ORIENTATION_VERTICAL, false, DockingMode.HORIZONTAL_TOOLBAR, DockingMode.VERTICAL_TOOLBAR);
        LineDock toolBarDock6 = new LineDock(LineDock.ORIENTATION_VERTICAL, false, DockingMode.HORIZONTAL_TOOLBAR, DockingMode.VERTICAL_TOOLBAR);
        GridDock toolGridDock = new GridDock(DockingMode.TOOL_GRID);


        //toolBarDock6.addDockable(buttonDockables[37], new Position(0));

        // Add the line docks to their composite parents.
        compositeToolBarDock1.addChildDock(toolBarDock1, new Position(0));
        compositeToolBarDock1.addChildDock(toolBarDock2, new Position(1));
        compositeToolBarDock1.addChildDock(toolBarDock3, new Position(2));
        compositeToolBarDock1.addChildDock(toolBarDock4, new Position(3));
        compositeToolBarDock2.addChildDock(toolBarDock5, new Position(0));
        compositeToolBarDock2.addChildDock(toolBarDock6, new Position(1));


        // Add the grid dock to the float dock.
        //floatDock.addChildDock(toolGridDock, new Position(screenSize.width / 2 + 100, screenSize.height / 2 - 170));

        // Minimize dockable 3, 4, 5, 6, 7.
        minimizer.visualizeDockable(dockables[1]);

        // Add the paths of the docked dockables to the model with the docking paths.
        addDockingPath(dockables[0]);
        addDockingPath(dockables[1]);
        addDockingPath(dockables[2]);

        // Add the path of the dockables that are not docked already.
        // We want dockable 8 to be docked, when it is made visible, where dockable 11 is docked.
        DockingPath dockingPathToCopy11 = DockingManager.getDockingPathModel().getDockingPath(dockables[1].getID());
        DockingPath dockingPath8 = DefaultDockingPath.copyDockingPath(dockables[0], dockingPathToCopy11);
        DockingManager.getDockingPathModel().add(dockingPath8);
        DockingPath dockingPathToCopy1 = DockingManager.getDockingPathModel().getDockingPath(dockables[0].getID());
        DockingPath dockingPath3 = DefaultDockingPath.copyDockingPath(dockables[1], dockingPathToCopy1);
        DockingManager.getDockingPathModel().add(dockingPath3);

        // Create the menubar.
        JMenuBar menuBar = createMenu(dockables);
        frame.setJMenuBar(menuBar);

    }

    /**
     * Decorates the given dockable with all state actions.
     *
     * @param dockable	The dockable to decorate.
     * @return			The wrapper around the given dockable, with actions.
     */
    private Dockable addAllActions(Dockable dockable) {

        Dockable wrapper = new StateActionDockable(dockable, new DefaultDockableStateActionFactory(), DockableState.statesClosed());
        wrapper = new StateActionDockable(wrapper, new DefaultDockableStateActionFactory(), DockableState.statesAllExceptClosed());
        return wrapper;

    }

    /**
     * Decorates the given dockable with some state actions (not maximized).
     *
     * @param dockable	The dockable to decorate.
     * @return			The wrapper around the given dockable, with actions.
     */
    private Dockable addLimitActions(Dockable dockable) {

        Dockable wrapper = new StateActionDockable(dockable, new DefaultDockableStateActionFactory(), DockableState.statesClosed());
        int[] limitStates = {DockableState.NORMAL, DockableState.MINIMIZED, DockableState.EXTERNALIZED};
        wrapper = new StateActionDockable(wrapper, new DefaultDockableStateActionFactory(), limitStates);
        return wrapper;

    }

    /**
     * Creates a dockable with a button as content.
     *
     * @param id			The ID of the dockable that has to be created.
     * @param title			The title of the dialog that will be displayed.
     * @param icon			The icon that will be put on the button.
     * @param message		The message that will be displayed when the action is performed.
     * @return				The dockable with a button as content.
     */
    private Dockable createButtonDockable(String id, String title, Icon icon, String message, Command command) {

        // Create the action.

        MessageAction action = new MessageAction(this, title, icon, message, command);
        // Create the button.
        ToolBarButton button = new ToolBarButton(action);

        // Create the dockable with the button as component.
        ButtonDockable buttonDockable = new ButtonDockable(id, button);

        // Add a dragger to the individual dockable.
        createDockableDragger(buttonDockable);

        return buttonDockable;

    }

    /**
     * Adds a drag listener on the content component of a dockable.
     */
    private void createDockableDragger(Dockable dockable) {

        // Create the dragger for the dockable.
        DragListener dragListener = DockingManager.getDockableDragListenerFactory().createDragListener(dockable);
        dockable.getContent().addMouseListener(dragListener);
        dockable.getContent().addMouseMotionListener(dragListener);

    }

    /**
     * Creates a dockable for a given content component.
     *
     * @param 	id 		The ID of the dockable. The IDs of all dockables should be different.
     * @param 	content The content of the dockable.
     * @param 	title 	The title of the dockable.
     * @param 	icon 	The icon of the dockable.
     * @return			The created dockable.
     * @throws 	IllegalArgumentException	If the given ID is null.
     */
    private Dockable createDockable(String id, Component content, String title, Icon icon, String description) {

        // Create the dockable.
        DefaultDockable dockable = new DefaultDockable(id, content, title, icon);

        // Add a description to the dockable. It will be displayed in the tool tip.
        dockable.setDescription(description);

        return dockable;

    }

    /**
     * Creates the menubar with menus: File, Window, Look and Feel, and Drag Painting.
     *
     * @param dockables		The dockables for which a menu item has to be created.
     * @return				The created menu bar.
     */
    private JMenuBar createMenu(Dockable[] dockables) {
        // Create the menu bar.
        JMenuBar menuBar = new JMenuBar();

        // Build the File menu.
        JMenu fileMenu = new JMenu("File");
        fileMenu.setMnemonic(KeyEvent.VK_F);
        fileMenu.getAccessibleContext().setAccessibleDescription("The File Menu");
        menuBar.add(fileMenu);

        // Build the Window menu.
        JMenu windowMenu = new JMenu("Window");
        windowMenu.setMnemonic(KeyEvent.VK_W);
        windowMenu.getAccessibleContext().setAccessibleDescription("The Window Menu");
        menuBar.add(windowMenu);

        // Build the Window menu.
        JMenu tradeMenu = new JMenu("Trade");
        tradeMenu.setMnemonic(KeyEvent.VK_T);
        tradeMenu.getAccessibleContext().setAccessibleDescription("The Trade Menu");
        menuBar.add(tradeMenu);


        // Build the Look and Feel menu.
        JMenu helpMenu = new JMenu("Help");
        helpMenu.setMnemonic(KeyEvent.VK_H);
        helpMenu.getAccessibleContext().setAccessibleDescription("Help Menu");
        menuBar.add(helpMenu);


        //menuBar.add(draggingMenu);
////////////////////////////////////////////////////////////////////////
        CommandController controller = new CommandController();

        // The JMenuItem for File
        JMenuItem menuModifyProfileItem = new JMenuItem("Modify Profile", KeyEvent.VK_M);
        menuModifyProfileItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.ALT_MASK));
        menuModifyProfileItem.getAccessibleContext().setAccessibleDescription("Modify Profile");
        menuModifyProfileItem.addActionListener(controller);
        menuModifyProfileItem.setActionCommand(Command.DISPLAY_MODIFY_PROFILE.toString());
        fileMenu.add(menuModifyProfileItem);
        // The JMenuItem for File
        JMenuItem menuItem = new JMenuItem("Exit", KeyEvent.VK_E);
        menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.ALT_MASK));
        menuItem.getAccessibleContext().setAccessibleDescription("Exit the application");
        menuItem.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                System.exit(0);
            }
        });
        fileMenu.add(menuItem);


        // The JMenuItems for the dockables.
        for (int index = 0; index < dockables.length; index++) {
            // Create the check box menu for the dockable.
            JCheckBoxMenuItem cbMenuItem = new DockableMenuItem(dockables[index]);
            windowMenu.add(cbMenuItem);
        }

        
        JMenu chartMenu = new JMenu("Chart");
        chartMenu.addActionListener(controller);
        //chartMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.ALT_MASK));
        //chartMenu.getAccessibleContext().setAccessibleDescription("Chart");
        
        JMenuItem selectGold = new JMenuItem("GOLD");
        JMenuItem selectSilver = new JMenuItem("SILVER");
        JMenuItem selectBTC = new JMenuItem("BTC");

        selectGold.setActionCommand(Command.SELECT_GOLD.toString());
        selectGold.addActionListener(controller);
        
        selectSilver.addActionListener(controller);
        selectSilver.setActionCommand(Command.SELECT_SILVER.toString());

        selectBTC.addActionListener(controller);
        selectBTC.setActionCommand(Command.SELECT_BTC.toString());
        
        chartMenu.add(selectGold);
        chartMenu.add(selectSilver);
        chartMenu.add(selectBTC);
        
        windowMenu.add(chartMenu);
        
        //Trade Menu:


        JMenuItem orderEntryItem = new JMenuItem("Order Entry", KeyEvent.VK_O);
        orderEntryItem.addActionListener(controller);
        orderEntryItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.ALT_MASK));
        orderEntryItem.getAccessibleContext().setAccessibleDescription("Order Entry");
        orderEntryItem.setActionCommand(Command.DISPLAY_ORDER_ENTRY.toString());
        tradeMenu.add(orderEntryItem);

        tradeMenu.add(new JSeparator());

        JMenuItem requestChequeItem = new JMenuItem("Withdraw Funds", KeyEvent.VK_W);
        requestChequeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, ActionEvent.ALT_MASK));
        requestChequeItem.addActionListener(controller);
        requestChequeItem.setActionCommand(Command.REQUEST_CHEQUE.toString());
        tradeMenu.add(requestChequeItem);

        JMenuItem requestDepositItem = new JMenuItem("Deposit Funds", KeyEvent.VK_D);
        requestDepositItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.ALT_MASK));
        requestDepositItem.addActionListener(controller);
        requestDepositItem.setActionCommand(Command.ADD_FUNDS_REQUEST.toString());
        tradeMenu.add(requestDepositItem);

        JMenuItem requestDeliveryItem = new JMenuItem("Request Delivery", KeyEvent.VK_R);
        requestDeliveryItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.ALT_MASK));
        requestDeliveryItem.addActionListener(controller);
        requestDeliveryItem.setActionCommand(Command.REQUEST_DELIVERY.toString());
        tradeMenu.add(requestDeliveryItem);

        tradeMenu.add(new JSeparator());

        JMenuItem aboutMenuItem = new JMenuItem("About", KeyEvent.VK_A);
        aboutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.ALT_MASK));
        aboutMenuItem.addActionListener(controller);
        aboutMenuItem.setActionCommand(Command.ABOUT.toString());
        //helpMenuItem.
        helpMenu.add(aboutMenuItem);

        JMenuItem helpMenuItem = new JMenuItem("Help", KeyEvent.VK_H);
        helpMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, ActionEvent.ALT_MASK));
        helpMenuItem.addActionListener(controller);
        helpMenuItem.setActionCommand(Command.HELP.toString());
        //helpMenuItem.
        helpMenu.add(helpMenuItem);

        if( ClientGlobals.user.isAdmin() ){
            JMenuItem adminOptions = new JMenuItem("Admin Options");
            adminOptions.addActionListener(controller);
            adminOptions.setActionCommand(Command.ADMIN_OPTIONS.toString());
            tradeMenu.add(adminOptions);
        }

        // should be on a submenu
        JMenuItem closeAccountItem = new JMenuItem("Close Account", KeyEvent.VK_Q);
        closeAccountItem.addActionListener(controller);
        closeAccountItem.setActionCommand(Command.CLOSE_ACCOUNT.toString());
        tradeMenu.add(closeAccountItem);


        // The JMenuItems for the look and feels.
        ButtonGroup group = new ButtonGroup();
        for (int index = 0; index < LAFS.length; index++) {
            LafMenuItem lafMenuItem = new LafMenuItem(this, LAFS[index]);
            group.add(lafMenuItem);
        }


        return menuBar;

    }

    /**
     * Sets the look and feel on the application.
     *
     * @param 	lafClassName	The class name of the new look and feel.
     */
    public void setLookAndFeel(LAF laf) {

        try {
            UIManager.setLookAndFeel(laf.getClassName());
            LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
            LAF.setTheme(lookAndFeel, laf.getTheme());
            UIManager.setLookAndFeel(lookAndFeel);

            // Iterate over the owner windows of the dock model.
            DockModel dockModel = DockingManager.getDockModel();
            for (int index = 0; index < dockModel.getOwnerCount(); index++) {

                // Set the LaF on the owner.
                Window owner = dockModel.getOwner(index);
                SwingUtilities.updateComponentTreeUI(owner);

                // Set the LaF on the floating windows.
                FloatDock floatDock = dockModel.getFloatDock(owner);
                for (int childIndex = 0; childIndex < floatDock.getChildDockCount(); childIndex++) {
                    Component floatingComponent = (Component) floatDock.getChildDock(childIndex);
                    SwingUtilities.updateComponentTreeUI(SwingUtilities.getWindowAncestor(floatingComponent));
                }

                // Set the LaF on all the dockable components.
                for (int dockableIndex = 0; dockableIndex < dockables.length; dockableIndex++) {
                    SwingUtilities.updateComponentTreeUI(dockables[dockableIndex].getContent());
                }
                

            }
        } catch (Exception e) {
        }

    }

    /**
     * Creates a docking path for the given dockable. It contains the information
     * how the dockable is docked now. The docking path is added to the docking path
     * model of the docking manager.
     *
     * @param	 dockable	The dockable for which a docking path has to be created.
     * @return				The docking path model. Null if the dockable is not docked.
     */
    private DockingPath addDockingPath(Dockable dockable) {

        if (dockable.getDock() != null) {
            // Create the docking path of the dockable.
            DockingPath dockingPath = DefaultDockingPath.createDockingPath(dockable);
            DockingManager.getDockingPathModel().add(dockingPath);
            return dockingPath;
        }

        return null;

    }
    
    public static void createAndShowLogin() {
        JDialog dialog = new JDialog();
        LoginPanel lp = new LoginPanel(dialog);
        dialog.setTitle("Login Screen");
        dialog.setContentPane(lp);
        dialog.setSize(new Dimension(345, 190));
        dialog.addWindowListener(
                new WindowListener() {

                    public void windowActivated(WindowEvent arg0) {
                    }

                    public void windowClosed(WindowEvent arg0) {
                    }

                    public void windowClosing(WindowEvent arg0) {
                        Application.quit();
                    }

                    public void windowDeactivated(WindowEvent arg0) {
                    }

                    public void windowDeiconified(WindowEvent arg0) {
                    }

                    public void windowIconified(WindowEvent arg0) {
                    }

                    public void windowOpened(WindowEvent arg0) {
                    }
                });

        //Center the frame window
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = dialog.getSize();

        if (frameSize.height > screenSize.height) {
            frameSize.height = screenSize.height;
        }

        if (frameSize.width > screenSize.width) {
            frameSize.width = screenSize.width;
        }

        dialog.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
        dialog.setModal(true);
        dialog.setAlwaysOnTop(true);
        dialog.setFocusCycleRoot(true);
        dialog.setFocusable(true);
        dialog.setEnabled(true);
        dialog.requestFocusInWindow();
        dialog.setVisible(true);
    }

    public static LAF[] LAFS;


    // Main method.
    public static void createAndShowGUI() {

        // Create login screen
        //if debug disable
        createAndShowLogin();
        //end if

        // Create the look and feels.
        LAFS = new LAF[9];
        LAFS[0] = new LAF("Substance", "org.jvnet.substance.skin.SubstanceModerateLookAndFeel", LAF.THEME_DEAULT);
        LAFS[1] = new LAF("Mac", "javax.swing.plaf.mac.MacLookAndFeel", LAF.THEME_DEAULT);
        LAFS[2] = new LAF("Metal", "javax.swing.plaf.metal.MetalLookAndFeel", LAF.THEME_DEAULT);
        LAFS[3] = new LAF("Liquid", "com.birosoft.liquid.LiquidLookAndFeel", LAF.THEME_DEAULT);
        LAFS[4] = new LAF("Windows", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel", LAF.THEME_DEAULT);
        LAFS[5] = new LAF("Nimrod Ocean", "com.nilo.plaf.nimrod.NimRODLookAndFeel", LAF.THEME_OCEAN);
        LAFS[6] = new LAF("Nimrod Gold", "com.nilo.plaf.nimrod.NimRODLookAndFeel", LAF.THEME_GOLD);
        LAFS[7] = new LAF("Nimbus", "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel", LAF.THEME_DEAULT);
        LAFS[8] = new LAF("TinyLaF", "de.muntjak.tinylookandfeel.TinyLookAndFeel", LAF.THEME_DEAULT);

        // Set the first enabled look and feel.
        for (int index = 0; index < LAFS.length; index++) {
            try {
                if (LAFS[index].isSupported()) {
                    LAFS[index].setSelected(true);
                    UIManager.setLookAndFeel(LAFS[index].getClassName());
                    break;
                }
            } catch (Exception e) {
            }
        }

        // Remove the borders from the split panes and the split pane dividers.
        LookAndFeelUtil.removeAllSplitPaneBorders();

        // Create the frame.
        final JFrame frame = new JFrame("BullionXpress Trader [" + SharedGlobals.version + "]");

        // Set the default location and size.
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        frame.setLocation((screenSize.width - FRAME_WIDTH) / 2, (screenSize.height - FRAME_HEIGHT) / 2);
        frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);

        // Create the panel and add it to the frame.
        final DockingFrame panel = new DockingFrame(frame);
        frame.getContentPane().add(panel);

        // Set the frame properties and show it.
        frame.addWindowListener(new WindowListener() {

            public void windowOpened(WindowEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            public void windowClosing(WindowEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
                Application.quit();
            }

            public void windowClosed(WindowEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            public void windowIconified(WindowEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            public void windowDeiconified(WindowEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            public void windowActivated(WindowEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            public void windowDeactivated(WindowEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

        });
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);


        ChartDataLoader worker = new ChartDataLoader();
        worker.start();
        ClientGlobals.cm.schedule();
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        
        int W = FRAME_WIDTH, H = FRAME_HEIGHT, FH = 50;
        Image img = panel.createImage(W,H);
        String periods = ".";
        while(!worker.isComplete()){
            try {
                periods += ".";
                if( periods.length() > 5 ){
                    periods = "";
                }
                Graphics bg = img.getGraphics();
                bg.clearRect(0, 0, W, H);

                Font font = new Font("Arial", Font.BOLD, FH);
                bg.setFont(font);
                bg.setColor(Color.black);
                String loading = "Loading";
                FontMetrics fm = bg.getFontMetrics();
                int strWidth = fm.stringWidth(loading);
                bg.drawString(loading + periods, W/2-(strWidth/2), (H/2)-(FH/2));
                panel.getGraphics().drawImage(img, 0, 0, panel);

                Thread.sleep(100);
            }
            catch (InterruptedException ex) {
                Logger.getLogger(DockingFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
    }

    

    public void initializeAndRun() {

        Runnable doCreateAndShowGUI = new Runnable() {

            public void run() {
                createAndShowGUI();
            }
        };
        SwingUtilities.invokeLater(doCreateAndShowGUI);
    }
}
